#ifndef __KERN_TRAP_TRAP_H__
#define __KERN_TRAP_TRAP_H__

#include <defs.h>
#include <riscv.h>
#include <clock.h>

#define TICK_NUM 100

/* save 32 regs */
struct regs {
    uint64_t zero;  // always zero
    uint64_t ra;    // return address
    uint64_t sp;    // stack pointer
    uint64_t gp;    // global pointer
    uint64_t tp;    // thread pointer
    uint64_t t0;    // temporary
    uint64_t t1;    // temporary
    uint64_t t2;    // temporary
    uint64_t s0;    // saved
    uint64_t s1;    // saved
    uint64_t a0;    // function argument
    uint64_t a1;    // function argument
    uint64_t a2;    // function argument
    uint64_t a3;    // function argument
    uint64_t a4;    // function argument
    uint64_t a5;    // function argument
    uint64_t a6;    // function argument
    uint64_t a7;    // function argument
    uint64_t s2;    // saved
    uint64_t s3;    // saved
    uint64_t s4;    // saved
    uint64_t s5;    // saved
    uint64_t s6;    // saved
    uint64_t s7;    // saved
    uint64_t s8;    // saved
    uint64_t s9;    // saved
    uint64_t s10;   // saved
    uint64_t s11;   // saved
    uint64_t t3;    // temporary
    uint64_t t4;    // temporary
    uint64_t t5;    // temporary
    uint64_t t6;    // temporary
};

/* save 36 regs */
struct trapframe
{
    struct regs gpr;
    uint64_t sstatus;    // sstatue
    uint64_t sepc;       // sepc
    uint64_t sbadvaddr;  // sbadvaddr
    uint64_t scause;     // scause
};

void trap(struct trapframe *tf);
void idt_init(void);
void print_regs(struct regs *gpr);
void print_trapframe(struct trapframe *tf);
void interrupt_handler(struct trapframe *tf);
void exception_handler(struct trapframe *tf);

#endif